/*
 * @Author: 李石
 * @Date: 2024-05-18 21:00:19
 * @LastEditors: error: git config user.name & please set dead value or install git
 * @LastEditTime: 2024-05-19 09:22:31
 * @Description: 
 * Copyright (c) 2024 by ${lishi0105@163.com}, All Rights Reserved. 
 */
#ifndef _BASE_DTO_HPP_
#define _BASE_DTO_HPP_

#include <iostream>
#include <string>
#include <stdint.h>
#include <nlohmann/json.hpp>

template<typename T>
class BaseDto {
public:
    using Ptr = std::shared_ptr<T>;

    // 创建 std::shared_ptr<T> 对象的静态方法
    static Ptr CreateShared() {
        return std::make_shared<T>();
    }

    // 序列化函数
    std::string ToString(bool pretty = true) const {
         try {
            if (pretty) {
                return nlohmann::json(*static_cast<const T*>(this)).dump(4); // 缩进4个空格
            } else {
                return nlohmann::json(*static_cast<const T*>(this)).dump();
            }
        } catch (const nlohmann::json::type_error& e) {
            std::cerr << "JSON type error: " << e.what() << std::endl;
        } catch (const std::exception& e) {
            std::cerr << "General exception: " << e.what() << std::endl;
        }
        return std::string("");
    }

    // 反序列化函数，带有异常处理，失败时返回 nullptr
    static Ptr Fetch(const std::string& jsonString) {
        try {
            Ptr dto = std::make_shared<T>();
            nlohmann::json json_obj = nlohmann::json::parse(jsonString);
            json_obj.get_to(*dto);
            return dto;
        } catch (const nlohmann::json::parse_error& e) {
            std::cerr << "JSON ["<<jsonString <<"] parse error: " << e.what() << std::endl;
        } catch (const nlohmann::json::type_error& e) {
            std::cerr << "JSON ["<<jsonString <<"] typ error: " << e.what() << std::endl;
        } catch (const std::exception& e) {
            std::cerr << "["<<jsonString <<"] General exception: " << e.what() << std::endl;
        }
        return nullptr;
    }
};

template<typename DtoType>
class ResponseDto {
public:
    using Ptr = std::shared_ptr<ResponseDto<DtoType>>;
    static Ptr CreateShared() {
        return std::make_shared<ResponseDto<DtoType>>();
    }
    int code;
    std::string msg;
    std::shared_ptr<DtoType> data;  // 可以为 nullptr

    // 为 ResponseDto 提供自定义的序列化方法
    friend void to_json(nlohmann::json& j, const ResponseDto& dto) {
        if (dto.data) {
            j = nlohmann::json{
                {"code", dto.code},
                {"msg", dto.msg},
                {"data", *dto.data}  // data 非空时解引用
            };
        } else {
            j = nlohmann::json{
                {"code", dto.code},
                {"msg", dto.msg},
                {"data", nullptr}  // data 为空时赋值为 nullptr
            };
        }
    }
    // 为 ResponseDto 提供自定义的反序列化方法
    friend void from_json(const nlohmann::json& j, ResponseDto& dto) {
        j.at("code").get_to(dto.code);
        j.at("msg").get_to(dto.msg);
        if (j.contains("data") && !j.at("data").is_null()) {
            dto.data = std::make_shared<DtoType>(j.at("data").get<DtoType>());
        } else {
            dto.data = nullptr;
        }
    }
    std::string ToString(bool pretty = false) const {
        nlohmann::json j = *this;  // 利用自定义的 to_json 方法自动转换为 JSON
        return pretty ? j.dump(4) : j.dump();  // 根据 pretty 参数选择输出格式
    }
};

class ErrMsgDto : public BaseDto<ErrMsgDto>{
public:
    std::string err;
    NLOHMANN_DEFINE_TYPE_INTRUSIVE(ErrMsgDto, err)
};

#endif // _BASE_DTO_HPP_